package com.cs224u.experimental;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import weka.clusterers.Clusterer;
import weka.clusterers.SimpleKMeans;
import weka.core.Attribute;
import weka.core.FastVector;
import weka.core.Instance;
import weka.core.Instances;
import weka.filters.Filter;
import weka.filters.unsupervised.attribute.StringToWordVector;

public class SimpleClusterer implements Serializable {

  private static final long serialVersionUID = 6623646459046924197L;

  private Instances m_Data = null;
  
  private StringToWordVector m_Filter = new StringToWordVector();
  
  private Clusterer m_Clusterer = new SimpleKMeans();
  //private Clusterer m_Clusterer = new EM();
  
  public SimpleClusterer() throws Exception {
    String nameOfDataset = "SimpleClusterer";
    
    FastVector attributes = new FastVector(1);
    attributes.addElement(new Attribute("Message", (FastVector) null));
    m_Data = new Instances(nameOfDataset, attributes, 100);
    
    m_Filter.setLowerCaseTokens(true);
  }
  
	public static void main(String[] options) throws Exception {
    List<String> trainingData = new ArrayList<String>();

    trainingData.add("I like coffee");
    trainingData.add("I like pizza");
    trainingData.add("Do you like computers?");
    trainingData.add("Winter is cold");
    trainingData.add("Buy viagra");
    trainingData.add("Download now");
    trainingData.add("Viagra viagra viagra");
    trainingData.add("Click here to try viagra");
    trainingData.add("Click on this link");
    trainingData.add("Viagra is good");
    trainingData.add("I like winter");
    trainingData.add("Pizza pizza pizza");
    
    SimpleClusterer clusterer = new SimpleClusterer();
    
    for(String message : trainingData) {
      clusterer.updateData(message);
    }
    
    clusterer.buildClusterer();
 
    for(String message : trainingData) {
      System.out.print(message + ":");
      clusterer.clusterMessage(message);      
    }    
	}

  private void clusterMessage(String message) throws Exception {
    if(m_Data.numInstances() == 0) {
      throw new Exception("No clusterer available.");
    }
    
    Instances testset = m_Data.stringFreeStructure();
    Instance instance = makeInstance(message, testset);
    m_Filter.input(instance);
    Instance filteredInstance = m_Filter.output();
    
//    for(int i = 0; i < filteredInstance.numAttributes(); i++) {
//      Attribute attribute = filteredInstance.attribute(i);
//      System.err.println(attribute.toString() + " " + filteredInstance.value(attribute));
//    }
    
    double predicted = m_Clusterer.clusterInstance(filteredInstance);
    System.out.println(predicted);
  }

  private void buildClusterer() throws Exception {
    m_Filter.setInputFormat(m_Data);
    Instances filteredData = Filter.useFilter(m_Data, m_Filter);
    m_Clusterer.buildClusterer(filteredData);
  }

  private void updateData(String message) {
    Instance instance = makeInstance(message, m_Data);
    m_Data.add(instance);
  }

  private Instance makeInstance(String text, Instances data) {
    Instance instance = new Instance(1);
    
    Attribute messageAtt = data.attribute("Message");
    instance.setValue(messageAtt, messageAtt.addStringValue(text));
    
    instance.setDataset(data);
    return instance;
  }
}
